import math
from Utilities.AutoGetOperator.selectPackage import get_func

Operator_IVQ_ROFS=get_func(r'Operators/OperationOperators/OperatorIVQROF.py','Operator_IVQ_ROFS')


class MAUT(Operator_IVQ_ROFS):
    def __init__(self,matrix,weight_list=[],q=3,gangliang=[]):
        '''
        function: MABAC决策方法
        :param matrix: 决策矩阵
        :param weight_list: 属性权重
        :param q: q值
        :param gangliang: 成本型或效益型表示，成本型用0表示，效益型用1表示
        '''
        super(MAUT,self).__init__(q=q)
        self.q=q
        self.matrix = matrix
        if len(weight_list):
            self.weight_list = weight_list
        else:
            self.weight_list = [1/len(matrix[0]) for i in range(len(matrix[0]))]
        # 检测是否传入纲量，若未传入，则全默认为效益型属性
        if len(gangliang):
            self.gangliang=gangliang
        else:
            self.gangliang=[1 for i in range(len(matrix[0]))]
        # 获得方案的最大最小

    def get_positive_negative(self, matrix):
        '''
        function: 获取没个方案中的最大最小值
        matirx: 决策矩阵
        :return: 最大最小值的向量
        '''

        score_matrix = [[self.getsco(j, self.q).getScore() for j in i] for i in self.matrix]
        temp = [[score_matrix[i][j] for i in range(len(score_matrix))] for j in range(len(score_matrix[0]))]
        # 获得最大值与最小值的下标
        max_index = [i.index(max(i)) for i in temp]
        min_index = [i.index(min(i)) for i in temp]
        positive = []
        negtive = []
        for mx, mn, j in zip(max_index, min_index, range(len(matrix[0]))):
            positive.append(self.matrix[mx][j])
            negtive.append(self.matrix[mn][j])

        return positive, negtive

    def getPosNor(self, Ivq, Pos, Neg, q):
        '''
        对正类型的指标进行处理
        :param Ivq: 区间值
        :param Pos: 正理想解元素
        :param Neg: 负理想解元素
        :param q: q值
        :return:
        '''
        PosNor = self.divid(self.subtract(Ivq, Neg, q), self.subtract(Pos, Neg, q), q)
        return PosNor

    def getNegNor(self, Ivq, Pos, Neg, q):
        '''
        对负类型指标进行处理
        题中用的是+1，本处改成+正理想元素
        :param Ivq:区间值
        :param Pos: 正理想解元素
        :param Neg: 负理想解元素
        :param q: q值
        :return:
        '''

        t = self.divid(self.subtract(Neg, Ivq, q), self.subtract(Pos, Neg, q), q)
        NegNor = self.addition(t, Pos, q)
        return NegNor

    def getNormalizedMatrix(self, Matrix, Positiveline, Negativeline, q):
        '''
        规范化矩阵
        :param Matrix:决策矩阵
        :param q:q值
        :return:Matrix规范化之后的矩阵
        '''
        for i in range(len(Matrix)):
            for j in range(len(Matrix[0])):
                if self.gangliang[j] == 1:
                    Matrix[i][j] = self.getPosNor(Matrix[i][j], Positiveline[j], Negativeline[j], q)
                else:
                    Matrix[i][j] = self.getNegNor(Matrix[i][j], Positiveline[j], Negativeline[j], q)
        return Matrix

    def getMarginalUtilityScore(self, normalizedMatrix):
        '''
        获取边际效用得分
        :param NormalizedMatrix:规范化矩阵
        :return:
        '''
        scoreMatrix = [[self.getsco(j, self.q).getScore() for j in i] for i in normalizedMatrix]
        marginalScoreMatirx = [[((math.e ** (j ** 2) - 1) / 1.71) for j in i] for i in scoreMatrix]
        return marginalScoreMatirx

    def getFinalUtilityScore(self, scoreMatrix, weight):
        '''
        获取最终效用得分
        :param ScoreMatrix: 得分矩阵
        :param Weight: 权重
        :return:
        '''
        U = []
        for Row in range(len(scoreMatrix)):
            u0 = 0
            for Column in range(len(scoreMatrix[0])):
                u0 += weight[Column] * scoreMatrix[Row][Column]
            U.append(u0)
        return U

    def getResult(self):
        poistive, negtive = self.get_positive_negative(self.matrix)
        normalizedMatrix = self.getNormalizedMatrix(self.matrix, poistive, negtive, self.q)
        scoreMatrix = self.getMarginalUtilityScore(normalizedMatrix)
        res = self.getFinalUtilityScore(scoreMatrix, self.weight_list)
        res=[i/sum(res) for i in res]
        return res
if __name__ == "__main__":
    li = [
        [([0.81539, 0.91785], [0.17128, 0.28772]), ([0.12374, 0.22949], [0.55729, 0.67911]),
         ([0.84635, 0.95753], [0.10662, 0.21768]), ([0.73433, 0.90407], [0.20174, 0.23691]), ],
        [([0.79202, 0.84776], [0.10917, 0.11366]), ([0.29818, 0.3131], [0.47785, 0.64139]),
         ([0.14316, 0.29861], [0.78271, 0.8032]), ([0.01997, 0.33824], [0.71369, 0.85874]), ],
        [([0.89511, 0.90987], [0.1782, 0.21547]), ([0.19584, 0.25518], [0.4043, 0.51519]),
         ([0.24707, 0.43495], [0.71766, 0.74854]), ([0.08338, 0.28006], [0.1259, 0.34247]), ],
        [([0.09222, 0.1264], [0.78533, 0.81673]), ([0.24999, 0.31601], [0.63687, 0.7492]),
         ([0.13707, 0.23335], [0.75133, 0.88383]), ([0.70681, 0.77778], [0.00605, 0.18418]), ],
        [([0.1876, 0.28807], [0.42117, 0.57172]), ([0.1311, 0.19959], [0.7644, 0.81178]),
         ([0.06145, 0.20426], [0.86783, 0.89045]), ([0.74275, 0.86356], [0.14231, 0.25652])]
    ]

    a = MAUT(li, [.2, .2, .3, .3, ], 3)
    res = a.getResult()
    print(res)